package com.ruoyi.flowable.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.flowable.cmd.DeployModelCmd;
import com.ruoyi.flowable.cmd.SaveModelEditCmd;
import com.ruoyi.flowable.controller.base.BaseFlowableController;
import com.ruoyi.flowable.entity.FlowableModel;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.entity.FlowableModelImp;
import com.ruoyi.flowable.entity.ModelQueryEntity;
import com.ruoyi.flowable.exception.FlowableModelKeyExistsException;
import com.ruoyi.flowable.exception.FlowableModelQueryException;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ModelQuery;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * @program: RuoYi-Vue
 * @description: 流程实例controller
 * @author: jhw
 * @create: 2021-03-30 15:23
 **/
@RestController
@RequestMapping("/process/model")
public class ProcessModelController extends BaseFlowableController {

    @GetMapping("/list")
    public TableDataInfo listProcess(ModelQueryEntity model){
        PageDomain pageDomain = TableSupport.buildPageRequest();
        ModelQuery modelQuery = repositoryService.createModelQuery();
        if(StringUtils.isNotEmpty(model.getName())){
            modelQuery.modelNameLike(model.getName());
        }
        if(StringUtils.isNotEmpty(model.getKey())){
            modelQuery.modelKey(model.getKey());
        }
        if(model.getDeployed()!=null){
            if(model.getDeployed()){
                modelQuery.deployed();
            }else {
                modelQuery.notDeployed();
            }
        }
        long count = modelQuery.count();
        List<Model> data = modelQuery.listPage((pageDomain.getPageNum()-1)* pageDomain.getPageSize(),pageDomain.getPageSize());
        TableDataInfo dataInfo = getDataTable(data);
        dataInfo.setTotal(count);
        return dataInfo;
    }


    /**
     * 新增模型
     * @param model
     * @return
     */
    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addModel(@RequestBody FlowableModelImp model){
        System.out.println(model.toString());
        checkModelKeyExists(model.getKey());
        Model newModel = repositoryService.newModel();
        newModel.setKey(model.getKey());
        newModel.setName(model.getName());
        newModel.setVersion(1);
        newModel.setCategory(model.getCategory());
        newModel.setMetaInfo(getMetaInfo(model.getName(),model.getDescription()));
        System.out.println(newModel.toString());
        repositoryService.saveModel(newModel);
        return  AjaxResult.success("新增成功");
    }

    /**
     * 查询流程
     */
    @GetMapping(value = {"/","/{processModelKey}"})
    public AjaxResult getModel(@PathVariable(value = "processModelKey")String processModelKey) throws UnsupportedEncodingException {
        if(StringUtils.isEmpty(processModelKey)){
            throw new FlowableModelQueryException("processModelKey is null");
        }
        ModelQuery modelQuery = repositoryService.createModelQuery();
        modelQuery.modelKey(processModelKey);
        Model model= modelQuery.singleResult();
        FlowableModel flowableModel = new FlowableModelImp();
        BeanUtils.copyProperties(model,flowableModel);
        byte[] xml = repositoryService.getModelEditorSource(flowableModel.getId());
        if(xml!=null){
            flowableModel.setEditor(new String(xml,"UTF-8"));
        }
        String description = model.getMetaInfo();
        if(StringUtils.isNotEmpty(description)){
            description = JSON.parseObject(description).getString("description");
        }
        flowableModel.setDescription(description);
        AjaxResult ajaxResult = AjaxResult.success();
        ajaxResult.put(AjaxResult.DATA_TAG,flowableModel);
        return ajaxResult;
    }

    /**
     * 修改模型
     * @param model
     */
    @Log(title = "流程模型管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult editModel(@RequestBody FlowableModelImp model){
        managementService.executeCommand(new SaveModelEditCmd(model.getId(), model.getKey(),
                model.getName(), model.getCategory(), model.getDescription()));
        return  AjaxResult.success("修改成功");
    }
    /**
     * 删除模型
     * @param
     */
    @Log(title = "流程模型管理", businessType = BusinessType.DELETE)
    @DeleteMapping (value = {"/","/{processModelKey}"})
    public AjaxResult deleteModel(@PathVariable(value = "processModelKey" ,required = true)String processModelKey){
        String[] idsArr = processModelKey.split(",");
        for(String id:idsArr){
            List<Model> list = repositoryService.createModelQuery().modelKey(id).list();
            for (Model model : list){
                repositoryService.deleteModel(model.getId());
            }
        }

        return  AjaxResult.success("删除成功");
    }
    /**
     * 保存流程模型设计
     */
    @Log(title = "流程模型管理", businessType = BusinessType.INSERT)
    @RequestMapping("/save")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveModelEdit(@RequestBody FlowableModelImp model){
        managementService.executeCommand(new SaveModelEditCmd(model.getId(),model.getEditor()));
        return AjaxResult.success("保存成功");
    }
    /**
     * 部署流程
     */
    @Log(title = "流程模型管理", businessType = BusinessType.INSERT)
    @PutMapping("/deployProcess")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deployProcess(String processModelId){
        managementService.executeCommand(new DeployModelCmd(processModelId));
        return AjaxResult.success("成功部署流程");
    }

    public void  checkModelKeyExists(String key){
        long count = repositoryService.createModelQuery().modelKey(key).count();
        if(count>0){
            throw new FlowableModelKeyExistsException(key);
        }
    }

    protected String getMetaInfo(String name, String description) {
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode metaInfo = objectMapper.createObjectNode();
        metaInfo.put("name", name);
        metaInfo.put("description", description);
        return metaInfo.toString();
    }
}
